#pragma semicolon 1
#pragma newdecls required

#include <sourcemod>
#include <sdktools>

#define PLUGIN_VERSION "1.0"

#define CVAR_FLAGS FCVAR_SPONLY|FCVAR_NOTIFY

int g_PointHurt;
char N[3];

ConVar l4d2_charger_jump_height;
ConVar l4d2_charger_damage_mult;

float f_charger_jump_height;
float f_charger_damage_mult;

public Plugin myinfo =
{
	name = "[L4D2]Charger Jump",
	author = "凌鹿",
	description = "Charger撞人带人飞.",
	version = PLUGIN_VERSION,
	url = "https://gitee.com/sweet-and-sour-bombs"
}

public void OnPluginStart()
{
	l4d2_charger_jump_height = CreateConVar("l4d2_charger_jump_height", "1000.0", "Charger撞击跳跃的高度 注意：范围必须在251.0~N的范围内才有效.", FCVAR_NOTIFY, true, 251.0);
	l4d2_charger_damage_mult = CreateConVar("l4d2_charger_damage_mult", "20.0", "Charger撞击跳跃后落地生还者受到的伤害.", FCVAR_NOTIFY, true, 0.0);
	
	l4d2_charger_jump_height.AddChangeHook(ConVarChanged);
	l4d2_charger_damage_mult.AddChangeHook(ConVarChanged);

	//AutoExecConfig(true, "l4d2_ChargerJump");

	HookEvent("charger_carry_start", Event_ChargerCarryStart);
	HookEvent("charger_carry_end", Event_ChargerCarryEnd);

	ConVarChanged(null, "", "");
}

public void ConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue)
{
	f_charger_jump_height = l4d2_charger_jump_height.FloatValue;
	f_charger_damage_mult = l4d2_charger_damage_mult.FloatValue;
}

public void OnMapStart()
{
	g_PointHurt = CreatePointHurt();
}

public Action Event_ChargerCarryStart(Event event, const char[] name, bool dontBroadcast)
{
	int client = GetClientOfUserId(GetEventInt(event, "userid"));
	CreateTimer(0.2, Timer_ChargerCarryStart, client, TIMER_FLAG_NO_MAPCHANGE);
	return Plugin_Continue;
}

public Action Timer_ChargerCarryStart(Handle timer, any client)
{
	Jump(client, f_charger_jump_height);
	return Plugin_Continue;
}

public Action Event_ChargerCarryEnd(Event event, const char[] name, bool dontBroadcast)
{
	int client = GetClientOfUserId(GetEventInt(event, "userid"));
	int victim = GetClientOfUserId(GetEventInt(event, "victim"));
	DoPointHurtForInfected(victim, client);
	return Plugin_Continue;
}

void Jump(int client, float height)
{
	if (!IsClientInGame(client)) return;
	float velo[3];
	velo[0] = GetEntPropFloat(client, Prop_Send, "m_vecVelocity[0]", 0);
	velo[1] = GetEntPropFloat(client, Prop_Send, "m_vecVelocity[1]", 0);
	velo[2] = GetEntPropFloat(client, Prop_Send, "m_vecVelocity[2]", 0);
	float vec[3];
	vec[0] = velo[0];
	vec[1] = velo[1];
	vec[2] = velo[2] + height;
	TeleportEntity(client, NULL_VECTOR, NULL_VECTOR, vec);
	return;
}

int CreatePointHurt()
{
	int pointHurt = CreateEntityByName("point_hurt");
	if (pointHurt != -1)
	{
		DispatchKeyValue(pointHurt, "Damage", "10");
		DispatchSpawn(pointHurt);
	}
	return pointHurt;
}

int DoPointHurtForInfected(int victim, int attacker)
{
	if (g_PointHurt > 0 && IsValidEdict(g_PointHurt))
	{
		if (IsValidClient(victim))
		{
			Format(N, 20, "target%d", victim);
			DispatchKeyValue(victim, "targetname", N);
			DispatchKeyValue(g_PointHurt, "DamageTarget", N);
			DispatchKeyValueFloat(g_PointHurt, "Damage", f_charger_damage_mult);
			DispatchKeyValue(g_PointHurt, "DamageType", "32");
			int var2;
			if (IsValidClient(attacker))
			{
				var2 = attacker;
			}
			else
			{
				var2 = -1;
			}
			AcceptEntityInput(g_PointHurt, "Hurt", var2);
		}
	}
	else
	{
		g_PointHurt = CreatePointHurt();
	}
	return 0;
}

bool IsValidClient(int client)
{
	if (client < 1 || client > MaxClients) return false;
	if (!IsClientInGame(client)) return false;
	return true;
}
